using System;
using System.Xml.XPath;

namespace CriticalSystems.Instrumentation.TraceWriters
{
    /// <summary>
    /// Factory for constructing a <see cref="FileTraceWriter"/>
    /// </summary>
    public class FileTraceWriterFactory : ITraceWriterFactory
    {
        private const int MaxBufferSize = 4096;
        private readonly TimeSpan BufferWriteInterval = TimeSpan.FromSeconds(3);

        /// <summary>
        /// Creates the trace writer using the supplied XML settings.
        /// </summary>
        /// <param name="fullTypeName">Full name of the type.</param>
        /// <param name="settings">The configuration settings.</param>
        /// <returns></returns>
        /// <remarks>Expects configuration like:
        /// <example>
        /// &lt;anyElement logFile="c:\logFiles\MyLogFile.log" [fileManagement="None|ArchiveOld|DeleteOld"] [maxFileSize=2046]" \&gt;
        /// </example>
        /// </remarks>
        public ITraceWriter Create(string fullTypeName, IXPathNavigable settings)
        {
            XPathNavigator nav = settings.CreateNavigator();
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }
            nav.MoveToFirstChild();
            string filePath = nav.GetAttribute("logFile", string.Empty);
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentException(Resource.FileTraceWriterMissingLogFileAttribute, "settings");
            }
            TraceFileManagement traceFileManagement = TraceFileManagement.None;
            string fileManagement = nav.GetAttribute("fileManagement", string.Empty);
            if (!string.IsNullOrEmpty(fileManagement))
            {
                try
                {
                    traceFileManagement =
                        (TraceFileManagement) Enum.Parse(typeof (TraceFileManagement), fileManagement, true);
                }
                catch (Exception)
                {
                    throw new ArgumentException(Resource.FileTraceWriterInvalidFileManagementAttribute, "settings");
                }
            }
            string fileSize = nav.GetAttribute("maxFileSize", string.Empty);
            int maxFileSize = 0;
            if (!string.IsNullOrEmpty(fileSize))
            {
                if (!int.TryParse(fileSize, out maxFileSize))
                {
                    throw new ArgumentException(Resource.FileTraceWriterInvalidMaxFileSizeAttribute, "settings");
                }
                maxFileSize = maxFileSize * 1024; // Convert to bytes.
            }
            return new FileTraceWriter(filePath, traceFileManagement, maxFileSize, MaxBufferSize,
                                       this.BufferWriteInterval);
        }
    }
}